package employee_evaluation

import (
	"goskeleton/app/global/variable"
	"goskeleton/app/model"
	"goskeleton/app/utils/data_bind"
	"time"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// CreateEmployeeEvaluationFactory 创建 EmployeeEvaluation 工厂函数
func CreateEmployeeEvaluationFactory(sqlType string) *EmployeeEvaluation {
	return &EmployeeEvaluation{BaseModel: model.BaseModel{DB: model.UseDbConn(sqlType)}}
}

type EmployeeEvaluation struct {
	model.BaseModel
	ID             uint    `gorm:"column:id;type:int unsigned;primaryKey;autoIncrement" json:"id"`
	EmployeeID     int     `gorm:"column:employee_id;type:int;not null" json:"employee_id" comment:"请假人"`
	DepartmentID   int     `gorm:"column:department_id;type:int;not null" json:"department_id" comment:"部门"`
	PositionID     int     `gorm:"column:position_id;type:int;not null" json:"position_id" comment:"职位"`
	Phone          string  `gorm:"column:phone;type:varchar(20);not null" json:"phone" comment:"联系方式"`
	LeaveType      string  `gorm:"column:leave_type;type:enum('sick','personal','annual','marriage','maternity','bereavement');default:null" json:"leave_type" comment:"请假类型（事假/病假/婚假/年假/调休）sick: 病假, personal: 事假, annual: 年假，marriage：婚假，maternity：产假，bereavement：丧假"`
	StartDate      string  `gorm:"column:start_date" json:"start_date" comment:"请假开始日期（仅日期，如 2025-08-18）"`
	EndDate        string  `gorm:"column:end_date" json:"end_date" comment:"请假结束日期（需晚于 start_date）"`
	Day            uint    `gorm:"column:day;type:int unsigned;default:0" json:"day" comment:"请假天数（跨天部分，如 2天）"`
	Hour           uint    `gorm:"column:hour;type:int unsigned;default:0" json:"hour" comment:"请假小时数（当天时间，0-23）"`
	Minute         uint    `gorm:"column:minute;type:int unsigned;default:0" json:"minute" comment:"请假分钟数（当小时内，0-59）"`
	DurationHours  float64 `gorm:"column:duration_hours;type:decimal(10,1);not null" json:"duration_hours" comment:"总时长（小时，自动计算）"`
	Reason         string  `gorm:"column:reason;type:text" json:"reason" comment:"备注说明"`
	ApplyTime      string  `gorm:"column:apply_time;type:datetime;not null" json:"apply_time" comment:"申请时间"`
	Type           string  `gorm:"column:type;type:enum('leave','overtime');default:null" json:"type" comment:"类型（leave：请假，overtime：加班）"`
	Status         string  `gorm:"column:status;type:enum('pending','approved','rejected','withdrawn');default:pending" json:"status" comment:"状态（pending：待审核，approved：已审核，rejected：已拒绝,withdrawn: 已撤回）"`
	EmployeeName   string  `gorm:"-" json:"name" comment:"申请人"`
	DepartmentName string  `gorm:"-" json:"department" comment:"部门"`
	PositionName   string  `gorm:"-" json:"position" comment:"职位"`
	CreatedAt      string  `gorm:"column:created_at" json:"created_at" comment:"创建时间"`
	UpdatedAt      string  `gorm:"column:updated_at" json:"updated_at" comment:"更新时间"`
	RejectionNote  string  `gorm:"column:rejection_note" json:"rejection_note" comment:"驳回理由"`
	DeleteStatus   int     `gorm:"column:delete_status" json:"delete_status"` // 是否删除 1否 2是
}

// TableName 表名
func (p *EmployeeEvaluation) TableName() string {
	return "tb_overtime_leave_record"
}

// InsertData 插入请假申请数据
func (e *EmployeeEvaluation) InsertData(c *OvertimeLeaveInsert) bool {
	var tmp EmployeeEvaluation

	// 直接从 OvertimeLeaveInsert 结构体复制数据到 EmployeeEvaluation 结构体
	tmp.EmployeeID = c.EmployeeID
	tmp.DepartmentID = c.DepartmentID
	tmp.PositionID = c.PositionID
	tmp.Phone = c.Phone
	tmp.LeaveType = c.LeaveType
	tmp.StartDate = c.StartDate // 修复字段映射
	tmp.EndDate = c.EndDate     // 修复字段映射
	tmp.Day = uint(c.Day)
	tmp.Hour = uint(c.Hour)
	tmp.Minute = uint(c.Minute)
	tmp.Reason = c.Reason
	tmp.ApplyTime = time.Now().Format(variable.DateFormat)
	tmp.Type = c.Type     // 修复字段映射
	tmp.Status = "pending"      // 默认状态为待审核

	// 如果 ApplyTime 为空，则设置为当前时间
	if tmp.ApplyTime == "" {
		tmp.ApplyTime = time.Now().Format(variable.DateFormat)
	}

	// 计算总时长（小时）
	tmp.DurationHours = float64(tmp.Day*24) + float64(tmp.Hour) + float64(tmp.Minute)/60.0

	if res := e.Create(&tmp); res.Error == nil {
		return true
	} else {
		variable.ZapLog.Error("EmployeeEvaluation 数据新增出错", zap.Error(res.Error))
	}

	return false
}

// UpdateData 更新请假申请数据
func (e *EmployeeEvaluation) UpdateData(c *gin.Context) bool {
	var tmp EmployeeEvaluation
	if err := data_bind.ShouldBindFormDataToModel(c, &tmp); err == nil {
		// 计算总时长（小时）
		tmp.DurationHours = float64(tmp.Day*24) + float64(tmp.Hour) + float64(tmp.Minute)/60.0

		if res := e.Updates(&tmp); res.Error == nil {
			return true
		} else {
			variable.ZapLog.Error("EmployeeEvaluation 数据更新出错", zap.Error(res.Error))
			return false
		}
	} else {
		variable.ZapLog.Error("EmployeeEvaluation 数据绑定出错", zap.Error(err))
	}
	return false
}

func (e *EmployeeEvaluation) CalcOvertimeLeave(recordType string,
	employeeID int, leaveType string, startDate string, endDate string, status string) (tmp *OvertimeLeaveRecord, bo bool) {

	query := e.Model(&EmployeeEvaluation{})
	if recordType != "" {
		query = query.Where("type = ?", recordType)
	}
	status = "approved"
	if status != "" {
		query = query.Where("status = ?", status)
	}
	if employeeID > 0 {
		query = query.Where("employee_id = ?", employeeID)
	}
	if leaveType != "" {
		query = query.Where("leave_type = ?", leaveType)
	}
	if startDate != "" && endDate != "" {
		// 查询日期范围有重叠的记录：
		// 1. 数据库end_date在参数startDate和endDate之间
		// 2. 或者数据库start_date在参数startDate和endDate之间
		query = query.Where("(end_date > ? AND end_date < ?) OR (start_date > ? AND start_date < ?)", startDate, endDate, startDate, endDate)
	} else if startDate != "" {
		// 仅提供开始日期时，保持原有逻辑
		query = query.Where("start_date >= ?", startDate)
	} else if endDate != "" {
		// 仅提供结束日期时，保持原有逻辑
		query = query.Where("end_date <= ?", endDate)
	}
	query.Select("sum(day) as day,sum(hour) as hour,sum(minute) as minute,count(distinct(employee_id)) as employee_num")
	query.Scan(&tmp)
	return tmp, true

}

// ListData 获取请假申请列表数据
func (e *EmployeeEvaluation) ListData(
	departmentIds []int,
	recordType string,
	page, limitItems int, order string,
	employeeID int, leaveType string, startDate string, endDate string, status string, excludeStatus bool) (totalCounts int64, tmp []*EmployeeEvaluation, total *OvertimeLeaveRecord) {

	counts := e.getCountsByWhere(departmentIds,recordType,employeeID, leaveType, startDate, endDate, status, excludeStatus)

	if counts == 0 {
		return 0, nil, nil
	}

	// Calculate overtime leave totals
	total, bo := e.CalcOvertimeLeave(recordType,
		employeeID, leaveType, startDate, endDate, status)
	if !bo {
		return 0, nil, nil
	}

	// 构建查询条件
	query := e.Model(&EmployeeEvaluation{})
	if recordType != "" {
		query = query.Where("type = ?", recordType)
	}
	if status != "" {
		query = query.Where("status = ?", status)
	}
	if len(departmentIds) > 0 {
		query = query.Where("department_id in (?)", departmentIds)
	}
	if excludeStatus {
		query = query.Where("status <> ?", "withdrawn")
	}
	if employeeID > 0 {
		query = query.Where("employee_id = ?", employeeID)
	}
	if leaveType != "" {
		query = query.Where("leave_type = ?", leaveType)
	}
	if startDate != "" && endDate != "" {
		// 查询日期范围有重叠的记录：
		// 1. 数据库end_date在参数startDate和endDate之间
		// 2. 或者数据库start_date在参数startDate和endDate之间
		query = query.Where("(end_date > ? AND end_date < ?) OR (start_date > ? AND start_date < ?)", startDate, endDate, startDate, endDate)
	} else if startDate != "" {
		// 仅提供开始日期时，保持原有逻辑
		query = query.Where("start_date >= ?", startDate)
	} else if endDate != "" {
		// 仅提供结束日期时，保持原有逻辑
		query = query.Where("end_date <= ?", endDate)
	}

	if res := query.Debug().Limit(limitItems).Offset(page).Order(order).Find(&tmp); res.Error == nil {
		variable.ZapLog.Debug("EmployeeEvaluation 数据查询成功", zap.Any("tmp", tmp))
		return counts, tmp, total
	} else {
		variable.ZapLog.Error("EmployeeEvaluation 数据查询出错", zap.Error(res.Error))
	}
	return 0, nil, nil
}

// ShowOneItem 根据ID获取单条请假申请记录
func (e *EmployeeEvaluation) ShowOneItem(id int) (tmp *EmployeeEvaluation) {
	if res := e.Where("id = ?", id).First(&tmp); res.Error == nil && tmp.ID > 0 {
		return tmp
	} else {
		variable.ZapLog.Error("EmployeeEvaluation 数据查询出错", zap.Error(res.Error))
	}
	return nil
}

// DeleteData 删除请假申请记录
func (e *EmployeeEvaluation) DeleteData(id int) bool {
	if res := e.Where("id = ?", id).Updates(map[string]interface{}{"delete_status": 2}); res.Error == nil {
		return true
	} else {
		variable.ZapLog.Error("EmployeeEvaluation 数据删除出错", zap.Error(res.Error))
		return false
	}
}

// getCountsByWhere 根据条件获取记录总数
func (e *EmployeeEvaluation) getCountsByWhere(departmentIds []int,recordType string, employeeID int, leaveType string, startDate string, endDate string, status string, excludeStatus bool) (counts int64) {
	query := e.Model(&EmployeeEvaluation{})
	if recordType != "" {
		query = query.Where("type = ?", recordType)
	}
	if len(departmentIds) > 0 {
		query = query.Where("department_id in (?)", departmentIds)
	}
	if employeeID > 0 {
		query = query.Where("employee_id = ?", employeeID)
	}
	if leaveType != "" {
		query = query.Where("leave_type = ?", leaveType)
	}
	if status != "" {
		query = query.Where("status = ?", status)
	}
	if excludeStatus {
		query = query.Where("status <> ?", "withdrawn")
	}

	if startDate != "" && endDate != "" {
		// 查询日期范围有重叠的记录：
		// 1. 数据库end_date在参数startDate和endDate之间
		// 2. 或者数据库start_date在参数startDate和endDate之间
		query = query.Where("(end_date > ? AND end_date < ?) OR (start_date > ? AND start_date < ?)", startDate, endDate, startDate, endDate)
	} else if startDate != "" {
		// 仅提供开始日期时，保持原有逻辑
		query = query.Where("start_date >= ?", startDate)
	} else if endDate != "" {
		// 仅提供结束日期时，保持原有逻辑
		query = query.Where("end_date <= ?", endDate)
	}

	if res := query.Debug().Count(&counts); res.Error == nil {
		variable.ZapLog.Debug("EmployeeEvaluation 数据查询成功", zap.Any("counts", counts))
		return counts
	} else {
		variable.ZapLog.Error("EmployeeEvaluation 数据查询出错", zap.Error(res.Error))
		return 0
	}
}

func (e *EmployeeEvaluation) ChangeStatus(id int, status string, rejectionNote string) bool {

	// 使用Model方法显式指定要操作的表
	if res := e.Model(&EmployeeEvaluation{}).Where("id = ?", id).Updates(map[string]interface{}{
		"status":         status,
		"rejection_note": rejectionNote,
	}); res.Error == nil {
		return true
	} else {
		variable.ZapLog.Error("EmployeeEvaluation 数据更新出错", zap.Error(res.Error))
		return false
	}
}

func (e *EmployeeEvaluation) GetAllDataByMonth(employeeId int, startDate string, endDate string, recordType string) (totalCounts int64, tmp []*EmployeeEvaluation, total *OvertimeLeaveRecord) {

	counts := e.getCountsByWhere([]int{},recordType, employeeId, "", startDate, endDate, "", false)

	if counts == 0 {
		return 0, nil, nil
	}

	// Calculate overtime leave totals
	total, bo := e.CalcOvertimeLeave(recordType,
		employeeId, "", startDate, endDate, "")
	if !bo {
		return 0, nil, nil
	}

	// 构建查询条件
	query := e.Model(&EmployeeEvaluation{})
	if recordType != "" {
		query = query.Where("type = ?", recordType)
	}

	if employeeId > 0 {
		query = query.Where("employee_id = ?", employeeId)
	}

	if startDate != "" && endDate != "" {
		// 查询日期范围有重叠的记录：
		// 1. 数据库end_date在参数startDate和endDate之间
		// 2. 或者数据库start_date在参数startDate和endDate之间
		query = query.Where("(end_date > ? AND end_date < ?) OR (start_date > ? AND start_date < ?)", startDate, endDate, startDate, endDate)
	} else if startDate != "" {
		// 仅提供开始日期时，保持原有逻辑
		query = query.Where("start_date >= ?", startDate)
	} else if endDate != "" {
		// 仅提供结束日期时，保持原有逻辑
		query = query.Where("end_date <= ?", endDate)
	}

	if res := query.Debug().Find(&tmp); res.Error == nil {
		variable.ZapLog.Debug("EmployeeEvaluation 数据查询成功", zap.Any("tmp", tmp))
		return counts, tmp, total
	} else {
		variable.ZapLog.Error("EmployeeEvaluation 数据查询出错", zap.Error(res.Error))
	}
	return 0, nil, nil


}

// func (e *EmployeeEvaluation) CalcOvertimeLeave(employeeId int) (tmp *OvertimeLeaveRecord) {

// 	query := e.Model(&EmployeeEvaluation{})
// 	query.Select("sum(day) as day,sum(hour) as hour,sum(minute) as minute,count(distinct(employee_id)) as employee_num")
// 	if employeeId > 0 {
// 		query = query.Where("employee_id = ?", employeeId)
// 	}

// 	query.Where("status = ?", "approved")
// 	if res := query.Scan(&tmp); res.Error == nil {
// 		return tmp
// 	}
// 	return nil
// }

func (e *EmployeeEvaluation) CheckIsExist(recordType string, employeeId int,startDate,endDate string) bool {

	query := e.Model(&EmployeeEvaluation{})
	if recordType != "" {
		query = query.Where("type = ?", recordType)
	}
	if employeeId > 0 {
		query = query.Where("employee_id = ?", employeeId)
	}
	if startDate != "" && endDate != "" {
		// 查询日期范围有重叠的记录：
		// 1. 数据库end_date在参数startDate和endDate之间
		// 2. 或者数据库start_date在参数startDate和endDate之间
		query = query.Where("(start_date <= ? AND end_date >= ?) OR (start_date <= ? AND end_date >= ?) OR (start_date > ? AND end_date < ?)", startDate, startDate, endDate, endDate,startDate,endDate)
	} else if startDate != "" {
		// 仅提供开始日期时，保持原有逻辑
		query = query.Where("start_date >= ?", startDate)
	} else if endDate != "" {
		// 仅提供结束日期时，保持原有逻辑
		query = query.Where("end_date <= ?", endDate)
	}
	query = query.Where("status IN (?)", []string{"pending","approved"}  )
	var counts int64
	if res := query.Debug().Count(&counts); res.Error == nil {
		variable.ZapLog.Debug("EmployeeEvaluation 数据查询成功", zap.Any("counts", counts))
		return counts > 0
	} else {
		variable.ZapLog.Error("EmployeeEvaluation 数据查询出错", zap.Error(res.Error))
		return false
	}


}

